#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include "modbus_rtu485.h"
#include "../debug.h"
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "../misc.h"


#define UART2_DRIVER "/dev/ttyS2"
#define UART3_DRIVER "/dev/ttyS3"

#if(FAN_TYPE == NEW_FAN)
const mc_handle_t mcHandleTable[] = 
{
    {MC_HANDLE_INDEX_FAN1_SPEED_SET,    OT_WRITE,   ModbusRequest_Fan1Speed,              NULL},
    {MC_HANDLE_INDEX_FAN2_SPEED_SET,    OT_WRITE,   ModbusRequest_Fan2Speed,              NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_DATA,    OT_READ,    NULL,       ModbusRequest_ISOBoardAllInfor},
    {MC_HANDLE_INDEX_ISO_BOARD_FREQ_SET,OT_WRITE,   ModbusRequest_ISOBoardFreqSet,        NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_CS_SET,  OT_WRITE,   ModbusRequest_ISOBoardCsSet,          NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_CMD_SET, OT_WRITE,   ModbusRequest_ISOBoardCmdSet,         NULL},
};
#elif(FAN_TYPE == OLD_FAN)
const mc_handle_t mcHandleTable[] = 
{
    {MC_HANDLE_INDEX_FAN1_EN,           OT_WRITE,   ModbusRequest_Fan1TurnOn,             NULL},
    {MC_HANDLE_INDEX_FAN1_SPEED_SET,    OT_WRITE,   ModbusRequest_Fan1Speed,              NULL},
    {MC_HANDLE_INDEX_FAN2_EN,           OT_WRITE,   ModbusRequest_Fan2TurnOn,             NULL},
    {MC_HANDLE_INDEX_FAN2_SPEED_SET,    OT_WRITE,   ModbusRequest_Fan2Speed,              NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_DATA,    OT_READ,    NULL,       ModbusRequest_ISOBoardAllInfor},
    {MC_HANDLE_INDEX_ISO_BOARD_FREQ_SET,OT_WRITE,   ModbusRequest_ISOBoardFreqSet,        NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_CS_SET,  OT_WRITE,   ModbusRequest_ISOBoardCsSet,          NULL},
    {MC_HANDLE_INDEX_ISO_BOARD_CMD_SET, OT_WRITE,   ModbusRequest_ISOBoardCmdSet,         NULL},
};
#endif


void* modbus_rtu_uart2_thread(void* arg){

    const ConfigData *config_data = get_config_data_instance();
    InterfaceOptions uart2 = config_data->uart2;
    Misc_InitThread(__func__);
    
    if (strcmp(uart2.mode, "slave") == 0){
        create_rtu_slave_connect(&uart2,UART2_DRIVER);
    }
    else if(strcmp(uart2.mode, "master") == 0){
        create_rtu_master_connect(&uart2,UART2_DRIVER);
    }
    else{
        fprintf(stderr, "config file error!!\n");
    }
    return NULL;
}

void* modbus_rtu_uart3_thread(void* arg){
    const ConfigData *config_data = get_config_data_instance();
    InterfaceOptions uart3 = config_data->uart3;
    Misc_InitThread(__func__);
    
    if (strcmp(uart3.mode, "slave") == 0){
        create_rtu_slave_connect(&uart3,UART3_DRIVER);
    }
    else if(strcmp(uart3.mode, "master") == 0){
        create_rtu_master_connect(&uart3,UART3_DRIVER);
    }
    else{
        fprintf(stderr, "config file error!!\n");
    }
    return NULL;
}

int create_rtu_master_connect(InterfaceOptions *uart,const char* driver){

    modbus_t * modbus_ctx = NULL;

    printf("uart->baud is [%d]\n",uart->baud);
    printf("uart->parity is [%s]\n",&(uart->parity));
    printf("uart->data_bit is [%d]\n",uart->data_bit);
    printf("uart->stop_bit is [%d]\n",uart->stop_bit);
    printf("driver is [%s]\n",driver);

    modbus_ctx = modbus_new_rtu(driver, uart->baud, uart->parity, uart->data_bit, uart->stop_bit);
    if (modbus_ctx == NULL)
    {
        printf("[%s][%d] init rtu connect fail\n", __func__, __LINE__);
        return -1;
    }

    /* 启用debug */
    modbus_set_debug(modbus_ctx, TRUE);
    modbus_rtu_set_serial_mode(modbus_ctx, MODBUS_RTU_RS485);

    /* 连接设备 */
    while(modbus_connect(modbus_ctx) < 0){
        sleep(20);
    }

    while(1)
    {
        for(int idx = 0; idx < MC_HANDLE_INDEX_QTY; idx++)
        {
            if(idx == MC_HANDLE_INDEX_ISO_BOARD_CMD_SET)
            { 
                continue;
            }
            printf("[%s][%d] idx[%d]\n", __func__, __LINE__, idx);
            master_comm_do(modbus_ctx, &mcHandleTable[idx]);
            usleep(50000);
        }
    }

    modbus_close(modbus_ctx);
    modbus_free(modbus_ctx);
    return 0;
}

int create_rtu_slave_connect(InterfaceOptions *uart,const char* driver){

    printf("[%s][%d] driver is %s\n", __func__, __LINE__, driver);
    struct modbus_info_s modbus_info;
    memset(&modbus_info, 0, sizeof(struct modbus_info_s));
    modbus_t * modbus_ctx = NULL;
    modbus_mapping_t* mb_map;
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
    int rc;

    modbus_ctx = modbus_new_rtu(driver, uart->baud, uart->parity, uart->data_bit, uart->stop_bit);
    if (modbus_ctx == NULL)
    {
        printf("[%s][%d] creat_rtu_slave_connect fail\n", __func__, __LINE__);
        return -1;
    }

    /* 启用debug */
    modbus_set_debug(modbus_ctx, TRUE);

    /* 从站slave */
    modbus_set_slave(modbus_ctx, uart->slave_id);

    mb_map = modbus_mapping_new(50, 50, 20073, 50);
    if (mb_map == NULL)
    {
        printf("[%s][%d] mapping fail\n", __func__, __LINE__);
        modbus_free(modbus_ctx);
        return -1;
    }

    /* 连接设备 */
    while(modbus_connect(modbus_ctx) < 0){
        sleep(20);
    }

    modbus_rtu_set_serial_mode(modbus_ctx, MODBUS_RTU_RS485);

    while(1)
    {
        rc = modbus_receive(modbus_ctx, query);

        if (rc > 0)
        {
            
            int ret = parse_modbus_message(modbus_ctx, query, rc, mb_map, &modbus_info);
            if (ret == 0)
            {
                if (!modbus_recv_message_handler(modbus_ctx, query, rc, mb_map, &modbus_info))
                {
                    modbus_reply(modbus_ctx, query, rc, mb_map, &modbus_info);
                }
            }
            else if (ret == 1)
            {
                /* 不处理直接reply */
                modbus_reply(modbus_ctx, query, rc, mb_map, &modbus_info);
            }
        }
    }

    modbus_mapping_free(mb_map);
    modbus_close(modbus_ctx);
    modbus_free(modbus_ctx);

    return 0;
}